import { NextRequest, NextResponse } from 'next/server'
import { GloableResponseItem, ResponseEnum } from '@/utils/request/res'
import { Auth, DbScheme, type ExtendedNextApiRequest, generateToken, hashPassword, LogOperation, ResponseHandler, verifyPassword, verifyToken } from '@/utils/decorator'
import prisma from '@/utils/db/PrismaService'
import { BaseController } from '@/utils/request/BaseController'
import { getCurrentTimeInShanghai } from '@/utils'
import { createNoticeSchema, updateNoticeSchema } from '@/dbSchema/systemSchema'
import { GET as HttpGet, POST as HttpPost, PUT as HttpPut, DELETE as HttpDelete } from '@/utils/decorator'
import { createAllMethodHandlers } from '@/utils/request/routeRegistry'
import { Prisma } from '@prisma/client'
import { eventEmitter } from '@/utils/sse/EventEmitter'

class SystemNoticeController extends BaseController {
  // 获取通知列表
  @Auth()
  @ResponseHandler()
  @HttpGet()
  static async getNoticeList(request: ExtendedNextApiRequest) {
    const params: any = request.customBody
    const page = parseInt(params.current || params.page || '1')
    const pageSize = parseInt(params.pageSize || '10')
    const offset = (page - 1) * pageSize

    const whereConditions = ['del_flag = 1']
    const queryParams: any[] = []

    if (params.title) {
      whereConditions.push('title LIKE ?')
      queryParams.push(`%${params.title}%`)
    }

    if (params.notice_type) {
      whereConditions.push('notice_type = ?')
      queryParams.push(params.notice_type)
    }

    if (params.status !== undefined) {
      whereConditions.push('status = ?')
      queryParams.push(parseInt(params.status))
    }

    const whereClause = whereConditions.join(' AND ')

    const data = await prisma.$queryRaw<any[]>(
      Prisma.sql`
        SELECT *
        FROM sys_notice
        WHERE ${Prisma.raw(whereClause)}
        ORDER BY create_time DESC
        LIMIT ${pageSize} OFFSET ${offset}
      `
    )

    const total = await prisma.$queryRaw<{ count: BigInt }[]>(
      Prisma.sql`
        SELECT COUNT(*) as count
        FROM sys_notice
        WHERE ${Prisma.raw(whereClause)}
      `
    )

    const formatData = data.map(item => ({
      ...item,
      key: item.id
    }))

    return GloableResponseItem(ResponseEnum.success, "", {
      list: formatData || [],
      total: total[0]?.count ? Number(total[0].count) : 0,
      current: page,
      pageSize,
    })
  }

  // 获取我的通知列表
  @Auth()
  @ResponseHandler()
  @HttpGet()
  static async getMyNoticeList(request: ExtendedNextApiRequest) {
    const params: any = request.customBody
    const page = parseInt(params.current || params.page || '1')
    const pageSize = parseInt(params.pageSize || '10')
    const offset = (page - 1) * pageSize
    const userId = request.user?.id

    const data = await prisma.$queryRaw<any[]>(
      Prisma.sql`
        SELECT snu.*, sn.title, sn.content, sn.notice_type, sn.priority, sn.create_time as notice_create_time
        FROM sys_notice_user snu
        LEFT JOIN sys_notice sn ON snu.notice_id = sn.id
        WHERE snu.user_id = ${userId}
        ${params.read_status !== undefined ? Prisma.sql`AND snu.read_status = ${parseInt(params.read_status)}` : Prisma.sql``}
        ORDER BY snu.id DESC
        LIMIT ${pageSize} OFFSET ${offset}
      `
    )

    const total = await prisma.$queryRaw<{ count: BigInt }[]>(
      Prisma.sql`
        SELECT COUNT(*) as count
        FROM sys_notice_user
        WHERE user_id = ${userId}
        ${params.read_status !== undefined ? Prisma.sql`AND read_status = ${parseInt(params.read_status)}` : Prisma.sql``}
      `
    )

    const formatData = data.map(item => ({
      ...item,
      key: item.id,
      notice: {
        title: item.title,
        content: item.content,
        notice_type: item.notice_type,
        priority: item.priority,
        create_time: item.notice_create_time
      }
    }))

    return GloableResponseItem(ResponseEnum.success, "", {
      list: formatData || [],
      total: total[0]?.count ? Number(total[0].count) : 0,
      current: page,
      pageSize,
    })
  }

  // 获取通知详情
  @Auth()
  @ResponseHandler()
  @HttpGet()
  static async getNoticeDetail(request: ExtendedNextApiRequest) {
    const params: any = request.customBody
    const noticeId = parseInt(params.id)

    const notice = await prisma.sysNotice.findFirst({
      where: {
        id: noticeId,
        del_flag: 1
      },
      include: {
        noticeUsers: {
          select: {
            id: true,
            user_id: true,
            user_name: true,
            read_status: true,
            send_status: true,
            send_time: true,
            read_time: true
          }
        }
      }
    })

    if (!notice) {
      return GloableResponseItem(ResponseEnum.fail, "通知不存在", null)
    }

    return GloableResponseItem(ResponseEnum.success, "", notice)
  }

  // 获取未读通知数量
  @Auth()
  @ResponseHandler()
  @HttpGet()
  static async getUnreadCount(request: ExtendedNextApiRequest) {
    const userId = request.user?.id

    if (!userId) {
      return GloableResponseItem(ResponseEnum.fail, "用户信息无效", null)
    }

    const count = await prisma.sysNoticeUser.count({
      where: {
        user_id: parseInt(userId.toString()),
        read_status: 0
      }
    })

    return GloableResponseItem(ResponseEnum.success, "", { count })
  }

  // 获取通知统计
  @Auth()
  @ResponseHandler()
  @HttpGet()
  static async getNoticeStats(request: ExtendedNextApiRequest) {
    const currentTime = getCurrentTimeInShanghai()
    const todayStart = currentTime.split(' ')[0] + ' 00:00:00'
    const todayEnd = currentTime.split(' ')[0] + ' 23:59:59'

    // 总通知数
    const totalCount = await prisma.sysNotice.count({
      where: { del_flag: 1 }
    })

    // 已发送数
    const sentCount = await prisma.sysNotice.count({
      where: { del_flag: 1, status: 1 }
    })

    // 草稿数
    const draftCount = await prisma.sysNotice.count({
      where: { del_flag: 1, status: 0 }
    })

    // 今日发送数
    const todaySentCount = await prisma.sysNotice.count({
      where: {
        del_flag: 1,
        status: 1,
        create_time: {
          gte: todayStart,
          lte: todayEnd
        }
      }
    })

    return GloableResponseItem(ResponseEnum.success, "", {
      totalCount,
      sentCount,
      draftCount,
      todaySentCount
    })
  }

  // 新增通知
  @Auth()
  @ResponseHandler()
  @HttpPost()
  @DbScheme(createNoticeSchema)
  @LogOperation({
    module: "通知管理",
    operationName: "新增通知"
  })
  static async addNotice(request: ExtendedNextApiRequest) {
    const data = request.customBody
    const currentTime = getCurrentTimeInShanghai()

    // 数据类型转换和验证
    const target_ids = Array.isArray(data.target_ids) ? data.target_ids : []
    const send_config = typeof data.send_config === 'object' ? data.send_config : {}

    const notice = await prisma.sysNotice.create({
      data: {
        title: data.title?.toString() || '',
        content: data.content?.toString() || '',
        notice_type: data.notice_type || 'info',
        priority: typeof data.priority === 'number' ? data.priority : 0,
        send_type: data.send_type || 'manual',
        send_time: data.send_time || null,
        send_config: target_ids.length > 0 || Object.keys(send_config).length > 0 ? JSON.stringify(data.send_config) : null,
        target_type: data.target_type || 'user',
        target_ids: target_ids.length > 0 ? JSON.stringify(target_ids) : null,
        creator_id: request.user?.id ? parseInt(request.user.id.toString()) : 0,
        creator_name: request.user?.user_name || '',
        status: 0, // 草稿状态
        create_time: currentTime,
        update_time: currentTime,
        del_flag: 1
      }
    })

    return GloableResponseItem(ResponseEnum.success, "新增成功", notice)
  }

  // 更新通知
  @Auth()
  @ResponseHandler()
  @HttpPut()
  @DbScheme(updateNoticeSchema)
  @LogOperation({
    module: "通知管理",
    operationName: "更新通知"
  })
  static async updateNotice(request: ExtendedNextApiRequest) {
    const data = request.customBody
    const currentTime = getCurrentTimeInShanghai()

    // 数据类型转换和验证
    const target_ids = Array.isArray(data.target_ids) ? data.target_ids : []
    const send_config = typeof data.send_config === 'object' ? data.send_config : {}

    // 构建更新数据对象，只包含非空字段
    const updateData: any = {
      update_time: currentTime
    }

    if (data.title !== undefined) {
      updateData.title = data.title?.toString() || ''
    }
    if (data.content !== undefined) {
      updateData.content = data.content?.toString() || ''
    }
    if (data.notice_type !== undefined) {
      updateData.notice_type = data.notice_type
    }
    if (data.priority !== undefined) {
      updateData.priority = typeof data.priority === 'number' ? data.priority : 0
    }
    if (data.send_type !== undefined) {
      updateData.send_type = data.send_type
    }
    if (data.send_time !== undefined) {
      updateData.send_time = data.send_time || null
    }
    if (data.send_config !== undefined) {
      updateData.send_config = target_ids.length > 0 || Object.keys(send_config).length > 0 ? JSON.stringify(data.send_config) : null
    }
    if (data.target_type !== undefined) {
      updateData.target_type = data.target_type
    }
    if (data.target_ids !== undefined) {
      updateData.target_ids = target_ids.length > 0 ? JSON.stringify(target_ids) : null
    }

    const notice = await prisma.sysNotice.update({
      where: { id: data.id },
      data: updateData
    })

    return GloableResponseItem(ResponseEnum.success, "更新成功", notice)
  }

  // 删除通知
  @Auth()
  @ResponseHandler()
  @HttpDelete()
  @LogOperation({
    module: "通知管理",
    operationName: "删除通知"
  })
  static async deleteNotice(request: ExtendedNextApiRequest) {
    const data = request.customBody
    const currentTime = getCurrentTimeInShanghai()

    await prisma.sysNotice.updateMany({
      where: {
        id: {
          in: data.ids.map((id: string) => parseInt(id))
        }
      },
      data: {
        del_flag: 0,
        update_time: currentTime
      }
    })

    return GloableResponseItem(ResponseEnum.success, "删除成功", null)
  }

  // 发送通知
  @Auth()
  @ResponseHandler()
  @HttpPost()
  @LogOperation({
    module: "通知管理",
    operationName: "发送通知"
  })
  static async sendNotice(request: ExtendedNextApiRequest) {
    const data = request.customBody
    const noticeId = parseInt(data.id)
    const currentTime = getCurrentTimeInShanghai()

    // 获取通知详情
    const notice = await prisma.sysNotice.findFirst({
      where: {
        id: noticeId,
        del_flag: 1
      }
    })

    if (!notice) {
      return GloableResponseItem(ResponseEnum.fail, "通知不存在", null)
    }

    if (notice.status === 1) {
      return GloableResponseItem(ResponseEnum.fail, "通知已发送，请勿重复发送", null)
    }

    // 获取目标用户列表
    const targetUsers = await SystemNoticeController.getTargetUsers(notice)

    if (targetUsers.length === 0) {
      return GloableResponseItem(ResponseEnum.fail, "没有找到目标用户", null)
    }

    // 更新通知状态为发送中
    await prisma.sysNotice.update({
      where: { id: noticeId },
      data: {
        status: 2,
        update_time: currentTime
      }
    })

    // 创建通知用户关联记录
    const noticeUserData = targetUsers.map(user => ({
      notice_id: noticeId,
      user_id: user.id,
      user_name: user.user_name,
      send_status: 0,
      read_status: 0
    }))

    await prisma.sysNoticeUser.createMany({
      data: noticeUserData
    })

    // 发送SSE通知
    let successCount = 0
    let failCount = 0

    for (const user of targetUsers) {
      try {
        // 发送SSE通知
        eventEmitter.emit(`user_${user.id}`, 'notice', {
          id: notice.id,
          title: notice.title,
          content: notice.content,
          notice_type: notice.notice_type,
          priority: notice.priority,
          create_time: notice.create_time
        })

        // 更新发送状态为成功
        await prisma.sysNoticeUser.updateMany({
          where: {
            notice_id: noticeId,
            user_id: user.id
          },
          data: {
            send_status: 1,
            send_time: currentTime,
            send_method: 'sse'
          }
        })

        successCount++
      } catch (error) {
        // 更新发送状态为失败
        await prisma.sysNoticeUser.updateMany({
          where: {
            notice_id: noticeId,
            user_id: user.id
          },
          data: {
            send_status: 2,
            send_time: currentTime,
            send_method: 'sse',
            error_msg: error instanceof Error ? error.message : '发送失败'
          }
        })

        failCount++
      }
    }

    // 更新通知状态
    const finalStatus = failCount === 0 ? 1 : (successCount === 0 ? 3 : 1) // 全部成功:1, 全部失败:3, 部分成功:1

    await prisma.sysNotice.update({
      where: { id: noticeId },
      data: {
        status: finalStatus,
        update_time: currentTime
      }
    })

    // 记录发送日志
    await prisma.sysNoticeLog.create({
      data: {
        notice_id: noticeId,
        send_method: 'sse',
        target_type: notice.target_type,
        target_count: targetUsers.length,
        success_count: successCount,
        fail_count: failCount,
        send_time: currentTime,
        cost_time: 0, // 可以记录实际耗时
        result: `成功发送${successCount}条，失败${failCount}条`
      }
    })

    return GloableResponseItem(ResponseEnum.success, "发送完成", {
      message: '发送完成',
      total: targetUsers.length,
      success: successCount,
      fail: failCount
    })
  }

  // 标记通知为已读
  @Auth()
  @ResponseHandler()
  @HttpPost()
  static async markNoticeRead(request: ExtendedNextApiRequest) {
    const data = request.customBody
    const currentTime = getCurrentTimeInShanghai()
    const userId = request.user?.id

    if (!userId) {
      return GloableResponseItem(ResponseEnum.fail, "用户信息无效", null)
    }

    await prisma.sysNoticeUser.updateMany({
      where: {
        notice_id: parseInt(data.notice_id),
        user_id: parseInt(userId.toString())
      },
      data: {
        read_status: 1,
        read_time: currentTime
      }
    })

    return GloableResponseItem(ResponseEnum.success, "标记成功", null)
  }

  // 获取目标用户列表（静态方法）
  private static async getTargetUsers(notice: any) {
    let users: any[] = []

    switch (notice.target_type) {
      case 'all':
        // 发送给所有用户
        users = await prisma.sysUser.findMany({
          where: { del_flag: 1, status: '0' },
          select: { id: true, user_name: true }
        })
        break
        
      case 'user':
        // 发送给指定用户
        if (notice.target_ids) {
          const userIds = JSON.parse(notice.target_ids)
          users = await prisma.sysUser.findMany({
            where: {
              id: { in: userIds.map((id: string) => parseInt(id)) },
              del_flag: 1,
              status: '0'
            },
            select: { id: true, user_name: true }
          })
        }
        break
        
      case 'role':
        // 发送给指定角色的用户
        if (notice.target_ids) {
          const roleTypes = JSON.parse(notice.target_ids)
          users = await prisma.sysUser.findMany({
            where: {
              role_type: { in: roleTypes },
              del_flag: 1,
              status: '0'
            },
            select: { id: true, user_name: true }
          })
        }
        break
        
      case 'dept':
        // 发送给指定部门的用户
        if (notice.target_ids) {
          const deptIds = JSON.parse(notice.target_ids)
          users = await prisma.sysUser.findMany({
            where: {
              dept_id: { in: deptIds.map((id: string) => parseInt(id)) },
              del_flag: 1,
              status: '0'
            },
            select: { id: true, user_name: true }
          })
        }
        break
    }
    
    return users
  }
}

// 使用自动路由处理器创建所有HTTP方法处理函数
const handlers = createAllMethodHandlers(SystemNoticeController)

export const { GET, POST, PUT, DELETE } = handlers 